package com.paypalpay.controller.pay;

import com.paypalpay.config.WxPayConstants;
import com.paypalpay.entity.common.UserboundPaymentOrder;
import com.paypalpay.entity.pay.WXNotificationpaymentResults;
import com.paypalpay.service.UserboundPaymentOrderService;
import com.paypalpay.service.WeixinNotificationpaymentService;
import com.paypalpay.util.pay.WxPayUtil;
import com.paypalpay.util.wx.MD5;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.net.URLEncoder;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Map;

@Controller
public class WeiXinPayH5Controller {

    private static Logger logger = Logger.getLogger(WeiXinPayH5Controller.class);
    @Autowired
    private HttpSession session;
    @Autowired
    WeixinNotificationpaymentService weixinNotificationpaymentService;
    @Autowired
    UserboundPaymentOrderService userboundPaymentOrderService;
    //微信支付的货币肯定是CNY人民币
    private String currency_code = "CNY";
    //微信H5支付Type为1
    private String payType = "1";

    /**
     * 微信H5支付
     *
     * @param request
     * @param
     * @param
     * @throws Exception
     */
    @RequestMapping("/wxPayH5")
    @CrossOrigin
    @ResponseBody
    public String wxPayH5(HttpServletRequest request) throws Exception {
        //http://localhost:8081/paypalpay/wxPayH5?deviceId=89862211334455000000&deviceType=4&requestOrderId=P0005132019&orderId=0001&partnerCode=P000513&packageCode=DP20180903000086&orderPeriod=1&orderUnit=1&amount=0.01&isOpen=1&paymentOrderId=00002
        System.out.println("weixin支付H5请求的链接是：" + request.getRequestURL() + "?" + request.getQueryString());
        String deviceId = request.getParameter("deviceId");
        String deviceType = request.getParameter("deviceType");
        String orderId = request.getParameter("orderId");
        String partnerCode = request.getParameter("partnerCode");
        String packageCode = request.getParameter("packageCode");
        String orderPeriod = request.getParameter("orderPeriod");
        String orderUnit = request.getParameter("orderUnit");
        String amount = request.getParameter("amount");
        String isOpen = request.getParameter("isOpen");
        String paymentOrderId = request.getParameter("paymentOrderId");
        String requestOrderId = request.getParameter("requestOrderId");

        System.out.println("deviceId：" + deviceId + ";orderId:" + orderId + ";paymentOrderId:" + paymentOrderId + ";requestOrderId:" + requestOrderId);

        if (deviceType == null || deviceId == null || orderId == null || amount == null || currency_code == null || partnerCode == null || packageCode == null || orderPeriod == null || orderUnit == null || paymentOrderId == null || isOpen == null) {
            System.out.println("参数不齐全");
        } else {
            System.out.println("参数至少是齐全的");

            // 根据packageCode去查询一下当前用户购买的套餐名称，并且插入到数据库
            String packageName = "";
            System.out.println("packageCode是什么多少：" + packageCode);
            if (packageCode.contains(",") == true) {
                // 此情况说明packageCode有多个套餐
                String[] str = packageCode.split(",");
                for (int i = 0; i < str.length; i++) {
                    String packages = str[i];
                    packageName += userboundPaymentOrderService.getPackageNameBypackages(packages, partnerCode) + ",";
                    System.out.println("取到的套餐名称：" + packageName);
                }
            } else {
                System.out.println("开始取name");
                //根据前面得到的code去数据库查询name
                //packageName = internationalPayPackageService.getPackageNameBypackageCode(packageCode);
                packageName = userboundPaymentOrderService.getPackageNameByPackageCode(packageCode, partnerCode);
                System.out.println("取到的套餐名称：" + packageName);
            }

            if (!orderId.equals("") && !"undefined".equals(orderId)) {
                //paypal支付当然是非微信用户访问
                System.out.println("微信H5支付支付前入库！");

                UserboundPaymentOrder paymentOrder = new UserboundPaymentOrder();
                paymentOrder.setPartnerCode(partnerCode);
                paymentOrder.setPackageCode(packageCode);
                paymentOrder.setPackageName(packageName);
                paymentOrder.setRequestOrderId(requestOrderId);
                paymentOrder.setPaymentOrderId(paymentOrderId);
                paymentOrder.setOrderId(orderId);
                paymentOrder.setDeviceId(deviceId);
                paymentOrder.setAmount(amount);
                paymentOrder.setOrderPeriod(orderPeriod);
                paymentOrder.setOrderUnit(orderUnit);
                paymentOrder.setIsOpen(isOpen);
                paymentOrder.setPayType(payType);
                paymentOrder.setOrderCurrency(currency_code);
                // 根据收到的deviceId去更新数据表，deviceId此时是有的，所以不能为null,openid为空
                userboundPaymentOrderService.updateUserboundNotWeixinPaymentOrder(paymentOrder);

//                int c = userboundPaymentOrderService.findOrderIdAndDeviceId(paymentOrderId, orderId, deviceId, amount);
//                if (c > 0) {
//                    //数据库有空行
//                    System.out.println("微信支付更新数据记录！");
//                    UserboundPaymentOrder paymentOrder = new UserboundPaymentOrder();
//                    paymentOrder.setPartnerCode(partnerCode);
//                    paymentOrder.setPackageCode(packageCode);
//                    paymentOrder.setPackageName(packageName);
//                    paymentOrder.setRequestOrderId(requestOrderId);
//                    paymentOrder.setPaymentOrderId(paymentOrderId);
//                    paymentOrder.setOrderId(orderId);
//                    paymentOrder.setDeviceId(deviceId);
//                    paymentOrder.setAmount(amount);
//                    paymentOrder.setOrderPeriod(orderPeriod);
//                    paymentOrder.setOrderUnit(orderUnit);
//                    paymentOrder.setIsOpen(isOpen);
//                    paymentOrder.setPayType(payType);
//                    paymentOrder.setOrderCurrency(currency_code);
//                    // 根据收到的deviceId去更新数据表，deviceId此时是有的，所以不能为null,openid为空
//                    userboundPaymentOrderService.updateUserboundNotWeixinPaymentOrder(paymentOrder);
//                } else {
//                    //数据库没有这条数据，自己加一条
//                    System.out.println("微信支付多写一条记录！");
//                    UserboundPaymentOrder paymentOrder = new UserboundPaymentOrder();
//                    paymentOrder.setPartnerCode(partnerCode);
//                    paymentOrder.setPackageCode(packageCode);
//                    paymentOrder.setPackageName(packageName);
//                    paymentOrder.setRequestOrderId(requestOrderId);
//                    paymentOrder.setPaymentOrderId(paymentOrderId);
//                    paymentOrder.setOrderId(orderId);
//                    paymentOrder.setDeviceId(deviceId);
//                    paymentOrder.setDeviceType(deviceType);
//                    paymentOrder.setAmount(amount);
//                    paymentOrder.setOrderPeriod(orderPeriod);
//                    paymentOrder.setOrderUnit(orderUnit);
//                    paymentOrder.setIsOpen(isOpen);
//                    paymentOrder.setPayType(payType);
//                    paymentOrder.setOrderCurrency(currency_code);
//                    // 根据收到的deviceId去更新数据表，deviceId此时是有的，所以不能为null,openid为空
//                    userboundPaymentOrderService.InsertUserboundNotWeixinPaymentOrder(paymentOrder);
//
//                }


            }
        }
        // 统一下单，返回xml，用return_code判断统一下单结果,获取prepay_id等预支付成功信息
        String jsonString = "";// 返回的json字串儿
        try {
            // 获取ip地址:
            String ipAddrStr1 = WxPayUtil.getIpAddr(request);
            System.out.println("原来获取的ip地址是：" + ipAddrStr1);
            String ipAddrStr = WeiXinPayH5Controller.getIp2(request);
            System.out.println("新的获取的ip地址是：" + ipAddrStr);
            // 将传过来的金额处理一下
            boolean flag = WeixinPayController.isInteger(amount);
            //商品描述
            //String body="领科物联网卡-流量重值";
            String body = "IotCardTrafficRecharge";
            //场景信息
            String scene_info = "{\"h5_info\":\"h5_info\" {\"type\":\"WAP\",\"wap_url\":\"http://wx.linksfield.net\",\"wap_name\":\"IotCardTrafficRecharge\"}}";
            // 如果是整型
            if (flag == true) {
                try {
                    int Amount = Integer.valueOf(amount).intValue();
                    int totel_fee = Amount * 100;
                    String prePayInfoXml = WxPayUtil.UnifiedOrderH5(body, scene_info, paymentOrderId, totel_fee, ipAddrStr);
                    logger.info("Controller中的prePayInfoXml：" + prePayInfoXml);
                    // 生成包含prepay_id的map，map传入前端
                    Map<String, Object> map = new HashMap<String, Object>();
                    //map = WxPayUtil.getPayMap(prePayInfoXml);

                    map = WxPayUtil.getPayH5Map(prePayInfoXml);
                    // System.out.println("Controller中的map：" + map);
                    logger.info("Controller中的map：" + map);

                    String prepay_id = (String) map.get("prepay_id");
                    request.setAttribute("prepay_id", prepay_id);

                    String mweb_url = (String) map.get("mweb_url");
                    request.setAttribute("mweb_url", mweb_url);

                    HashMap map1 = new HashMap();

                    map1.put("prepay_id", prepay_id);

                    map1.put("mweb_url", mweb_url);

                    JSONObject jsonObject = JSONObject.fromObject(map1);
                    System.out.println("输出的结果是：" + jsonObject);
                    // 3、将json对象转化为json字符串
                    jsonString = jsonObject.toString();
                    System.out.println(jsonString);
                    return jsonString;

                } catch (NumberFormatException e) {
                    e.printStackTrace();
                }

            } else {
                try {
                    // DecimalFormat("#")表示float类型格式化时不要小数点了
                    DecimalFormat decimalFormat = new DecimalFormat("#");
                    float Amount = Float.parseFloat(amount);
                    int totel_fee = Integer.parseInt(decimalFormat.format(Amount * 100));
                    String prePayInfoXml = WxPayUtil.UnifiedOrderH5(body, scene_info, paymentOrderId, totel_fee, ipAddrStr);
                    logger.info("Controller中的prePayInfoXml：" + prePayInfoXml);
                    // 生成包含prepay_id的map，map传入前端
                    Map<String, Object> map = new HashMap<String, Object>();
                    map = WxPayUtil.getPayH5Map(prePayInfoXml);
                    // System.out.println("Controller中的map：" + map);
                    logger.info("Controller中的map：" + map);
                    // 将订单号放入map，用以支付后处理

                    String prepay_id = (String) map.get("prepay_id");
                    request.setAttribute("prepay_id", prepay_id);


                    String mweb_url = (String) map.get("mweb_url");
                    request.setAttribute("mweb_url", mweb_url);

                    HashMap map1 = new HashMap();

                    map1.put("prepay_id", prepay_id);
                    map1.put("mweb_url", mweb_url);
                    JSONObject jsonObject = JSONObject.fromObject(map1);
                    System.out.println("输出的结果是：" + jsonObject);
                    // 3、将json对象转化为json字符串
                    jsonString = jsonObject.toString();
                    System.out.println(jsonString);
                    return jsonString;

                } catch (Exception e) {
                    // TODO: handle exceptions
                    e.printStackTrace();
                }
            }

        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }
        return jsonString;
    }


    /***
     * 用于获取用户真实ip的方法
     * @param request
     * @return
     */
    public static String getIp2(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
            //多次反向代理后会有多个ip值，第一个ip才是真实ip
            int index = ip.indexOf(",");
            if (index != -1) {
                return ip.substring(0, index);
            } else {
                return ip;
            }
        }
        ip = request.getHeader("X-Real-IP");
        if (StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
            return ip;
        }
        return request.getRemoteAddr();
    }

    /**
     * 微信支出订单状态查询
     *
     * @param request
     * @param
     * @return
     */
    @ResponseBody
    @CrossOrigin
    @RequestMapping(value = "/wxH5orderQuery")
    public String orderQuery(HttpServletRequest request) throws Exception {

        System.out.println("微信H5支付订单查询：" + request.getRequestURL() + "?" + request.getQueryString());
        System.out.println("微信H5支付订单查询paymentOrderId的值是：" + request.getParameter("paymentOrderId"));
        // 返回的json字串儿
        String jsonString = "";
        String out_trade_no = request.getParameter("paymentOrderId");
        String transaction_id = "";
        System.out.println("取出的out_trade_no是：" + out_trade_no);

        String prePayInfoXml = WxPayUtil.orderQuery(transaction_id, out_trade_no);
        System.out.println("Controller中的prePayInfoXml：" + prePayInfoXml);

        String return_code = WxPayUtil.getXmlPara(prePayInfoXml, "return_code");
        String return_msg = WxPayUtil.getXmlPara(prePayInfoXml, "return_msg");
        String appid = WxPayUtil.getXmlPara(prePayInfoXml, "appid");
        String mch_id = WxPayUtil.getXmlPara(prePayInfoXml, "mch_id");
        String device_info = WxPayUtil.getXmlPara(prePayInfoXml, "device_info");
        String nonce_str = WxPayUtil.getXmlPara(prePayInfoXml, "nonce_str");
        String sign = WxPayUtil.getXmlPara(prePayInfoXml, "sign");
        String result_code = WxPayUtil.getXmlPara(prePayInfoXml, "result_code");
        String openid = WxPayUtil.getXmlPara(prePayInfoXml, "openid");
        String is_subscribe = WxPayUtil.getXmlPara(prePayInfoXml, "is_subscribe");
        String trade_type = WxPayUtil.getXmlPara(prePayInfoXml, "trade_type");
        out_trade_no = WxPayUtil.getXmlPara(prePayInfoXml, "out_trade_no");
        String bank_type = WxPayUtil.getXmlPara(prePayInfoXml, "bank_type");
        String total_fee = WxPayUtil.getXmlPara(prePayInfoXml, "total_fee");
        String fee_type = WxPayUtil.getXmlPara(prePayInfoXml, "fee_type");
        transaction_id = WxPayUtil.getXmlPara(prePayInfoXml, "transaction_id");
        String attach = WxPayUtil.getXmlPara(prePayInfoXml, "attach");
        String time_end = WxPayUtil.getXmlPara(prePayInfoXml, "time_end");
        String trade_state = WxPayUtil.getXmlPara(prePayInfoXml, "trade_state");

        // 根据返回xml计算本地签名
        String localSign =
                "appid=" + appid +
                        "&attach=" + attach +
                        "&bank_type=" + bank_type +
                        "&device_info=" + device_info +
                        "&fee_type=" + fee_type +
                        "&is_subscribe=" + is_subscribe +
                        "&mch_id=" + mch_id +
                        "&nonce_str=" + nonce_str +
                        "&openid=" + openid +
                        "&out_trade_no=" + out_trade_no +
                        "&result_code=" + result_code +
                        "&return_code=" + return_code +
                        "&return_msg=" + return_msg +
                        "&time_end=" + time_end +
                        "&total_fee=" + total_fee +
                        "&trade_state=" + trade_state +
                        "&trade_type=" + trade_type +
                        "&transaction_id=" + transaction_id +
                        "&key=" + WxPayConstants.KEY;// 注意这里的参数要根据ASCII码 排序
        //将数据MD5加密
        localSign = MD5.calcMD5(localSign).toUpperCase();
        logger.debug("查询接口本地签名是：" + localSign);
        System.out.println("查询接口本地签名是：" + localSign);
        logger.debug("查询微信支付签名是：" + sign);
        System.out.println("查询微信支付签名是：" + sign);

        //查询成功！返回结果给前端
        HashMap map1 = new HashMap();
        if (trade_state.equals("SUCCESS")) {
            map1.put("trade_state", "0");
        } else {
            map1.put("trade_state", "1");
        }
        JSONObject jsonObject = JSONObject.fromObject(map1);
        // 3、将json对象转化为json字符串
        jsonString = jsonObject.toString();
        System.out.println("输出的结果是：" + jsonString);
        return jsonString;

    }

    /**
     * 微信H5支付结果回调
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/wxH5Notify")
    @CrossOrigin
    public String notify(HttpServletRequest request, HttpServletResponse response) {
        String deviceId = (String) session.getAttribute("deviceId");
        String deviceType = (String) session.getAttribute("deviceType");
        try {
            logger.info("H5微信支付回调获取数据开始");
            Map rMap = WxPayUtil.getH5NotifyResult(request);

            logger.info("H5微信支付回调notify获取的数据：" + rMap.get("resXml") + "");
            // 向微信输出处理结果，如果成功（SUCCESS），微信就不会继续调用了，否则微信会连续调用8次
            // 告诉微信服务器，我收到信息了，不要在通知我了
            //response.getWriter().write(rMap.get("resXml") + "");

            logger.info("开始分析H5微信回调数据:");

            String paymentId = rMap.get("out_trade_no") + "";
            String result_code = rMap.get("result_code") + "";
            String return_code = rMap.get("return_code") + "";
            String total_fee = rMap.get("total_fee") + "";
            String appid = rMap.get("appid") + "";

            String bank_type = rMap.get("bank_type") + "";
            String cash_fee = rMap.get("cash_fee") + "";
            String fee_type = rMap.get("fee_type") + "";
            String is_subscribe = rMap.get("is_subscribe") + "";

            String mch_id = rMap.get("mch_id") + "";
            String nonce_str = rMap.get("nonce_str") + "";
            String openid = rMap.get("openid") + "";
            String out_trade_no = rMap.get("out_trade_no") + "";

            String sign = rMap.get("sign") + "";
            String time_end = rMap.get("time_end") + "";
            String trade_type = rMap.get("trade_type") + "";

            String transaction_id = rMap.get("transaction_id") + "";
            session.setAttribute("transaction_id", transaction_id);
            System.out.println("将微信订单号transaction_id存起来：" + transaction_id);
            System.out.println("此时存时的sessionid是：" + session.getId());

            //将微信回传的交易记录入库保存下来
            int c = userboundPaymentOrderService.findCountByOrderId(out_trade_no);
            if (c <= 0) {
                WXNotificationpaymentResults results = new WXNotificationpaymentResults();
                results.setAppid(appid);
                results.setBankType(bank_type);
                results.setCashFee(cash_fee);
                results.setFeeType(fee_type);
                results.setIsSubscribe(is_subscribe);
                results.setMchId(mch_id);
                results.setNonceStr(nonce_str);
                results.setOpenid(openid);
                results.setOutTradeNo(out_trade_no);
                results.setResultCode(result_code);
                results.setReturnCode(return_code);
                results.setSign(sign);
                results.setTimeEnd(time_end);
                results.setTotalFee(total_fee);
                results.setTradeType(trade_type);
                results.setTransactionId(transaction_id);
                results.setDeviceId(deviceId);
                results.setDeviceType(deviceType);

                weixinNotificationpaymentService.insertPaymentResults(results);
            }

            // 判断result_code和return_code同时是SUCCESS就return给北京
            if (result_code.equalsIgnoreCase("SUCCESS") || return_code.equalsIgnoreCase("SUCCESS")) {
                // 查询一下当前out_trade_no单号有没有通知过北京，要是通知过IsNotify肯定是0了，
                //根据微信回调的订单号去数据库查询当前记录是不是已经记录
                System.out.println("回调的支付订单号out_trade_no：" + out_trade_no);
                int count = userboundPaymentOrderService.findOrderIdByNotify(out_trade_no);
                if (count > 0) {
                    // 当前单号已经通知过了就不要再通知北京了
                    // System.out.println("当前数据库已经有接收到微信回调并且已经入库");
                } else {
                    //根据微信回调的数据入库是否成功支付，根据paymentId这个id去数据插入支付结果
                    UserboundPaymentOrder paymentOrder = new UserboundPaymentOrder();
                    // 成功就将PayRst设为1；不插入就数据库默认0
                    paymentOrder.setPayRst("success");
                    // 成功就要通知，数据库就记1，不成功就不通知数据库会默认0
                    paymentOrder.setIsNotify("1");
                    paymentOrder.setPaymentOrderId(paymentId);
                    System.out.println("回调的支付订单号paymentId：" + paymentId);
                    userboundPaymentOrderService.updatePayRst(paymentOrder);
                    System.out.println("==================================支付结果入库完成！");

                    // 去数据库查询一下out_trade_no这个单号对应的orderId
                    //String orderId = userboundPaymentOrderService.queryOrderIdByPaymentId(paymentId);

                    UserboundPaymentOrder userOrder = userboundPaymentOrderService.queryOrderByPaymentId(paymentId);

                    if (userOrder == null) {
                        System.out.println("没有查询到需要去做支付结果通知的数据！");
                    } else {
                        String partnerCode = userOrder.getPartnerCode();
                        String orderId = userOrder.getOrderId();
                        String DeviceId = userOrder.getDeviceId();
                        String DeviceType = userOrder.getDeviceType();
                        System.out.println("查询到的订单orderId是:" + orderId + ";DeviceId是:" + DeviceId + ";DeviceType是:" + DeviceType);

                        if (orderId != null && orderId.length() > 0) {
                            System.out.println("调用给北京回调支付通知的controller:");
                            //String orderId, String deviceId, String deviceType, String payType, String payAmount
                            return "forward:/payNotify?orderId=" + orderId + "&deviceId=" + DeviceId + "&deviceType=" + DeviceType + "&payType=" + payType + "&payAmount=" + total_fee + "" + "&partnerCode=" + partnerCode + "";

                        }
                    }
                }

            }
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }
        return null;
    }
}
